<template>
  <ContentWrap>
    <ElForm
      class="-mb-15px"
      :model="queryParams"
      ref="queryFormRef"
      :inline="true"
      label-width="68px"
    >
      <el-form-item label="菜单名称" prop="name">
        <el-input
          v-model="queryParams.name"
          class="!w-240px"
          clearable
          placeholder="请输入菜单名称"
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item label="状态" prop="status">
        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
          <el-option
            v-for="dict in common_enable_status"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button @click="handleQuery">
          <Icon icon="ep:search" class="mr-5px" />
          搜索
        </el-button>
        <el-button @click="resetQuery">
          <Icon icon="ep:refresh" class="mr-5px" />
          重置
        </el-button>
        <el-button
          type="primary"
          plain
          @click="openForm('create')"
          v-hasPermi="['system:menu:create']"
        >
          <Icon icon="ep:plus" class="mr-5px" />
          新增
        </el-button>
        <el-button type="danger" plain @click="toggleExpandAll">
          <Icon icon="ep:sort" class="mr-5px" />
          展开/折叠
        </el-button>
        <el-button plain @click="refreshMenu">
          <Icon class="mr-5px" icon="ep:refresh" />
          刷新菜单缓存
        </el-button>
      </el-form-item>
    </ElForm>
  </ContentWrap>

  <!-- 列表区域 -->
  <ContentWrap>
    <el-table
      v-loading="listLoading"
      :data="list"
      row-key="id"
      :default-expand-all="isExpandAll"
      v-if="refreshTable"
    >
      <el-table-column label="菜单名称" prop="name" width="250" show-overflow-tooltip />
      <el-table-column label="图标" prop="icon" width="100">
        <template #default="scope">
          <Icon :icon="scope.row.icon" />
        </template>
      </el-table-column>
      <el-table-column label="排序" prop="sort" width="60" />
      <el-table-column label="权限标识" prop="permission" show-overflow-tooltip />
      <el-table-column label="组件路径" prop="component" show-overflow-tooltip />
      <el-table-column label="组件名称" prop="componentName" show-overflow-tooltip />
      <el-table-column label="状态" prop="status" width="130">
        <template #default="scope">
          <el-switch
            class="ml-4px"
            v-model="scope.row.status"
            :disabled="!hasPermi('system:menu:update')"
            :active-value="EnableStatusEnum.Enabled"
            :inactive-value="EnableStatusEnum.Disabled"
            :loading="menuStatusUpdating[scope.row.id]"
            @change="(val) => handleStatusChanged(scope.row, val as number)"
          />
        </template>
      </el-table-column>
      <el-table-column label="菜单编号" prop="id" width="130" />
      <el-table-column label="操作">
        <template #default="scope">
          <el-button
            v-hasPermi="['system:menu:update']"
            link
            type="primary"
            @click="openForm('update', scope.row.id)"
          >
            编辑
          </el-button>
          <el-button
            v-hasPermi="['system:menu:create']"
            link
            type="primary"
            @click="openForm('create', undefined, scope.row.id, scope.row.type)"
          >
            新增
          </el-button>
          <el-button
            v-hasPermi="['system:menu:delete']"
            link
            type="danger"
            @click="handleDelete(scope.row.id)"
          >
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>
  </ContentWrap>

  <!-- 表单弹窗：添加/修改 -->
  <MenuForm ref="editFormRef" @success="getList" />
</template>

<script setup lang="ts">
import * as MenuApi from '@/api/system/menu'
import MenuForm from './MenuForm.vue'
import { handleTree } from '@/utils/tree'
import { EnableStatusEnum, SystemMenuTypeEnum } from '@/utils/constants'
import type { MenuVO } from '@/api/system/menu'
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
import { hasPermi } from '@/utils/perm'

defineOptions({ name: 'SystemMenu' })

const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const { wsCache } = useCache()
const { common_enable_status } = useIntDict(DICT_TYPE.common_enable_status)

const queryParams = reactive({
  name: undefined,
  status: undefined
})
const queryFormRef = ref()

const listLoading = ref(false) // 列表加载状态
const list = ref() // 列表数据
const isExpandAll = ref(false) // 是否展开
const refreshTable = ref(true) // 重新渲染表格状态(移除表格[false] -> 重新渲染[true])

const getList = async () => {
  listLoading.value = true
  try {
    const data = await MenuApi.getMenuList(queryParams)
    list.value = handleTree(data)
  } finally {
    listLoading.value = false
  }
}

/** 展开/折叠操作 */
const toggleExpandAll = () => {
  refreshTable.value = false
  isExpandAll.value = !isExpandAll.value
  nextTick(() => {
    refreshTable.value = true
  })
}

const handleQuery = () => {
  getList()
}

const resetQuery = () => {
  queryFormRef.value.resetFields()
  handleQuery()
}

const handleDelete = async (id: number) => {
  try {
    // 弹出确认框
    await message.delConfirm()
    // 发起删除请求
    await MenuApi.deleteMenu(id)
    // 成功提示
    message.success(t('common.delSuccess'))
    // 刷新列表(页码不变)
    await getList()
  } catch {}
}

const refreshMenu = async () => {
  try {
    await message.confirm('即将更新缓存刷新浏览器！')
    // 清空本地缓存，触发刷新从新获取
    wsCache.delete(CACHE_KEY.USER)
    wsCache.delete(CACHE_KEY.ROLE_ROUTES)
    location.reload()
  } catch {}
}

const editFormRef = ref<InstanceType<typeof MenuForm>>()
const openForm = (type: string, id?: number, parentId?: number, menuType?: string) => {
  let withMenuType: string | undefined = undefined
  if (menuType === SystemMenuTypeEnum.Dir) {
    withMenuType = SystemMenuTypeEnum.Menu
  } else if (menuType === SystemMenuTypeEnum.Menu) {
    withMenuType = SystemMenuTypeEnum.Button
  }
  editFormRef.value?.open(type, id, parentId, withMenuType)
}

/** 开启/关闭菜单的状态 */
const menuStatusUpdating = ref({}) // 菜单状态更新中的 menu 映射。key：菜单编号，value：是否更新中
const handleStatusChanged = async (menu: MenuVO, val: number) => {
  // 1. 标记 menu.id 更新中
  menuStatusUpdating.value[menu.id!] = true
  try {
    // 2. 发起更新状态
    await MenuApi.updateMenuStatus(menu.id!, val)
  } finally {
    // 3. 标记 menu.id 更新完成
    menuStatusUpdating.value[menu.id!] = false
  }
}

onMounted(() => {
  getList()
})
</script>

<style scoped lang="scss"></style>
